package luke.ui.components;

import luke.audio.generation.MusicGenerationParams;
import luke.audio.generation.RunningMusicGenerator;
import luke.audio.metadata.SongMetadataExtractor;
import luke.core.config.AppDataManager;
import luke.core.logging.LogUtil;
import luke.core.utils.PlaybackStateManager;
import luke.core.utils.SvgIconLoader;
import luke.core.utils.AppStateManager;
import luke.ui.dialogs.DonationDialog;
import luke.core.utils.LanguageManager; // 新增：导入LanguageManager

import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.ArrayList;
import java.util.prefs.Preferences;

public class ProductionPanel extends JPanel {

    private final SongMetadataExtractor songMetadataExtractor;
    private final AppDataManager appDataManager;

    private AnimatedProgressBar progressBar;
    private JButton generateSingleButton;
    private JButton generateMixButton;
    private JButton generateVideoButton;
    private JButton stopButton;
    private JButton openOutputFolderButton;
    private boolean isStopping = false;
    private JSlider targetBpmSlider;
    private JLabel targetBpmLabel;
    private JCheckBox keepOriginalSpeedCheckBox;

    private SwingWorker<Void, ProgressUpdate> currentWorker;
    private volatile boolean isStoppingOperation = false;
    private Preferences prefs = Preferences.userNodeForPackage(ProductionPanel.class);
    private AppStateManager appStateManager;
    private int targetBpm;
    private boolean keepOriginalSpeed;
    private List<File> selectedFiles;
    private String generationType;
    
    // 添加LanguageManager引用
    private LanguageManager languageManager;

    private enum OperationState {
        GENERATING, STOPPED
    }

    private void resetProgressBar() {
        SwingUtilities.invokeLater(() -> {
            progressBar.setValue(0);
            progressBar.setString(languageManager.getPanelText("production.ready"));
            progressBar.stopAnimation();
            progressBar.setIndeterminate(false);
        });
    }

    public ProductionPanel() {
        // 初始化LanguageManager
        this.languageManager = LanguageManager.getInstance();
        
        this.appStateManager = AppStateManager.getInstance();
        this.songMetadataExtractor = SongMetadataExtractor.getInstance();
        this.selectedFiles = appStateManager.getSharedSelectedFiles();
        this.appDataManager = AppDataManager.getInstance();
        setLayout(new BorderLayout());
        setBorder(BorderFactory.createTitledBorder(languageManager.getPanelText("production.title")));
        setMinimumSize(new Dimension(100, 120));
        setPreferredSize(new Dimension(800, 150));
        setMaximumSize(new Dimension(Short.MAX_VALUE, 200));

        createUI();
        setupEventHandlers();
        loadPersistedSettings();
    }

    private void createUI() {
        JPanel mainPanel = new JPanel(new BorderLayout());

        JPanel bpmPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5));
        bpmPanel.add(new JLabel(languageManager.getPanelText("production.bpm.label")));
        targetBpmSlider = new JSlider(60, 220, 180);
        targetBpmSlider.setMajorTickSpacing(30);
        targetBpmSlider.setMinorTickSpacing(5);
        targetBpmSlider.setPaintTicks(true);
        targetBpmSlider.setPaintLabels(true);
        targetBpmSlider.setPreferredSize(new Dimension(250, targetBpmSlider.getPreferredSize().height));
        bpmPanel.add(targetBpmSlider);
        targetBpmLabel = new JLabel("180");
        targetBpmLabel.setPreferredSize(new Dimension(30, targetBpmLabel.getPreferredSize().height));
        bpmPanel.add(targetBpmLabel);

        keepOriginalSpeedCheckBox = new JCheckBox(languageManager.getPanelText("production.keep.original.speed"));
        keepOriginalSpeedCheckBox.setSelected(false);
        bpmPanel.add(keepOriginalSpeedCheckBox);

        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5));
        generateSingleButton = new JButton(languageManager.getPanelText("production.generate.single"));
        generateSingleButton.putClientProperty("JButton.buttonType", "roundRect");
        SvgIconLoader.setButtonIcon(generateSingleButton, "ico/ic_generate_single.svg", 16, 16);

        generateMixButton = new JButton(languageManager.getPanelText("production.generate.mix"));
        generateMixButton.putClientProperty("JButton.buttonType", "roundRect");
        SvgIconLoader.setButtonIcon(generateMixButton, "ico/ic_generate_mix_audio.svg", 16, 16);

        generateVideoButton = new JButton(languageManager.getPanelText("production.generate.video"));
        generateVideoButton.putClientProperty("JButton.buttonType", "roundRect");
        SvgIconLoader.setButtonIcon(generateVideoButton, "ico/ic_generate_mix_video.svg", 16, 16);

        stopButton = new JButton(languageManager.getPanelText("production.stop"));
        stopButton.putClientProperty("JButton.buttonType", "roundRect");
        stopButton.setEnabled(false);
        SvgIconLoader.setButtonIcon(stopButton, "ico/stop.svg", 16, 16);

        openOutputFolderButton = new JButton(languageManager.getPanelText("production.open.folder"));
        openOutputFolderButton.putClientProperty("JButton.buttonType", "roundRect");
        SvgIconLoader.setButtonIcon(openOutputFolderButton, "ico/文件夹.svg", 16, 16);
        openOutputFolderButton.setEnabled(true);

        buttonPanel.add(generateSingleButton);
        buttonPanel.add(generateMixButton);
        buttonPanel.add(generateVideoButton);
        buttonPanel.add(stopButton);
        buttonPanel.add(openOutputFolderButton);

        JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5));
        progressBar = new AnimatedProgressBar();
        progressBar.setStringPainted(true);
        progressBar.setForeground(new Color(27, 121, 148));
        progressBar.setFont(new Font(progressBar.getFont().getName(), Font.PLAIN, 12));
        progressBar.setPreferredSize(new Dimension(400, 25));
        progressBar.setString(languageManager.getPanelText("production.ready")); // 初始化设置进度条文本为"就绪"
        statusPanel.add(progressBar);

        JPanel controlPanel = new JPanel(new GridLayout(3, 1, 5, 5));
        controlPanel.add(bpmPanel);
        controlPanel.add(buttonPanel);
        controlPanel.add(statusPanel);

        mainPanel.add(controlPanel, BorderLayout.CENTER);
        add(mainPanel, BorderLayout.CENTER);
    }

    private void setupEventHandlers() {
        targetBpmSlider.addChangeListener(e -> {
            targetBpm = targetBpmSlider.getValue();
            targetBpmLabel.setText(String.valueOf(targetBpm));
            persistTargetBpm(targetBpm);
        });

        keepOriginalSpeedCheckBox.addActionListener(e -> {
            keepOriginalSpeed = keepOriginalSpeedCheckBox.isSelected();
            targetBpmSlider.setEnabled(!keepOriginalSpeed);
            targetBpmLabel.setEnabled(!keepOriginalSpeed);
            persistKeepOriginalSpeed(keepOriginalSpeed);
        });

        generateSingleButton.addActionListener(e -> generateTracks("single"));
        generateMixButton.addActionListener(e -> generateTracks("mix"));
        generateVideoButton.addActionListener(e -> generateTracks("mix_video"));

        stopButton.addActionListener(e -> {
            if (isStopping) {
                return;
            }

            Frame parentFrame = JOptionPane.getFrameForComponent(this);
            int result = JOptionPane.showConfirmDialog(
                    parentFrame,
                    languageManager.getPanelText("production.confirm.stop"),
                    languageManager.getPanelText("production.stop.confirm"),
                    JOptionPane.YES_NO_OPTION,
                    JOptionPane.QUESTION_MESSAGE);

            if (result == JOptionPane.YES_OPTION) {
                isStopping = true;
                isStoppingOperation = true;
                resetProgressBar();
                stopButton.setText(languageManager.getPanelText("production.stop.stopping"));
                stopButton.setEnabled(false);

                new Thread(() -> {
                    stopCurrentOperation();

                    SwingUtilities.invokeLater(() -> {
                        isStopping = false;
                        stopButton.setText(languageManager.getPanelText("production.stop"));
                        stopButton.setEnabled(false);
                        resetUIAfterStop();
                    });
                }).start();
            }
        });

        openOutputFolderButton.addActionListener(e -> {
            try {
                String baseOutputDir = appStateManager.getAudioDirectory();
                if (!baseOutputDir.isEmpty()) {
                    File outputDir = new File(baseOutputDir, "out_audio");
                    if (outputDir.exists() && outputDir.isDirectory()) {
                        Desktop.getDesktop().open(outputDir);
                    } else {
                        if (outputDir.mkdirs()) {
                            Desktop.getDesktop().open(outputDir);
                        } else {
                            JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(ProductionPanel.this),
                                    languageManager.getPanelText("production.no.output.dir"), languageManager.getString("panel.common.error.title"), JOptionPane.ERROR_MESSAGE);
                        }
                    }
                } else {
                    JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(ProductionPanel.this),
                            languageManager.getPanelText("production.select.dir"), languageManager.getString("panel.common.warning.title"), JOptionPane.WARNING_MESSAGE);
                }
            } catch (Exception ex) {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(ProductionPanel.this),
                        languageManager.getString("production.open.output.error", ex.getMessage()), languageManager.getString("panel.common.error.title"), JOptionPane.ERROR_MESSAGE);
            }
        });
    }

    private void generateTracks(String generationType) {
        this.generationType = generationType;
        
        if (currentWorker != null && !currentWorker.isDone()) {
            JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(this),
                    languageManager.getPanelText("production.task.running"), languageManager.getString("panel.common.warning.title"), JOptionPane.WARNING_MESSAGE);
            return;
        }

        isStoppingOperation = false;

        String baseOutputDir = appStateManager.getAudioDirectory();
        if (baseOutputDir.isEmpty()) {
            JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(this),
                    languageManager.getPanelText("production.select.dir"), languageManager.getString("panel.common.warning.title"), JOptionPane.WARNING_MESSAGE);
            return;
        }

        if (selectedFiles.isEmpty()) {
            JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(this),
                    languageManager.getPanelText("production.select.files"), languageManager.getString("panel.common.warning.title"), JOptionPane.WARNING_MESSAGE);
            return;
        }

        String[] videoParams = {"1080p", "true"};
        String videoTitle = "";

        if (generationType.equals("mix_video")) {
            JPanel panel = new JPanel(new GridLayout(0, 1));
            panel.add(new JLabel(languageManager.getPanelText("production.video.resolution")));

            JRadioButton horizontal720p = new JRadioButton(languageManager.getPanelText("production.video.resolution.720p.horizontal"));
            JRadioButton horizontal1080p = new JRadioButton(languageManager.getPanelText("production.video.resolution.1080p.horizontal"));
            JRadioButton vertical720p = new JRadioButton(languageManager.getPanelText("production.video.resolution.720p.vertical"));
            JRadioButton vertical1080p = new JRadioButton(languageManager.getPanelText("production.video.resolution.1080p.vertical"));

            ButtonGroup group = new ButtonGroup();
            group.add(horizontal720p);
            group.add(horizontal1080p);
            group.add(vertical720p);
            group.add(vertical1080p);

            String[] savedVideoParams = appDataManager.getVideoResolutionPreference();
            String savedResolution = savedVideoParams[0];
            boolean savedIsLandscape = Boolean.parseBoolean(savedVideoParams[1]);

            if ("720p".equals(savedResolution) && savedIsLandscape) {
                horizontal720p.setSelected(true);
            } else if ("1080p".equals(savedResolution) && savedIsLandscape) {
                horizontal1080p.setSelected(true);
            } else if ("720p".equals(savedResolution) && !savedIsLandscape) {
                vertical720p.setSelected(true);
            } else if ("1080p".equals(savedResolution) && !savedIsLandscape) {
                vertical1080p.setSelected(true);
            } else {
                horizontal1080p.setSelected(true);
            }

            panel.add(horizontal720p);
            panel.add(horizontal1080p);
            panel.add(vertical720p);
            panel.add(vertical1080p);

            panel.add(new JLabel(languageManager.getPanelText("production.video.style")));

            JRadioButton imageSlideshow = new JRadioButton(languageManager.getPanelText("production.video.style.slideshow"));
            JRadioButton spectrumEnergy = new JRadioButton(languageManager.getPanelText("production.video.style.spectrum"));
            JRadioButton circularSpectrum = new JRadioButton(languageManager.getPanelText("production.video.style.circular"));
            JRadioButton starlightSpectrum = new JRadioButton(languageManager.getPanelText("production.video.style.starlight"));

            imageSlideshow.setToolTipText(languageManager.getPanelText("production.video.slideshow.tip"));
            spectrumEnergy.setToolTipText(languageManager.getPanelText("production.video.spectrum.tip"));
            circularSpectrum.setToolTipText(languageManager.getPanelText("production.video.circular.tip"));
            starlightSpectrum.setToolTipText(languageManager.getPanelText("production.video.starlight.tip"));

            ButtonGroup styleGroup = new ButtonGroup();
            styleGroup.add(imageSlideshow);
            styleGroup.add(spectrumEnergy);
            styleGroup.add(circularSpectrum);
            styleGroup.add(starlightSpectrum);

            String savedVideoStyle = appDataManager.getVideoStylePreference();
            if ("spectrum".equals(savedVideoStyle)) {
                spectrumEnergy.setSelected(true);
            } else if ("circular".equals(savedVideoStyle)) {
                circularSpectrum.setSelected(true);
            } else if ("starlight".equals(savedVideoStyle)) {
                starlightSpectrum.setSelected(true);
            } else {
                imageSlideshow.setSelected(true);
            }

            panel.add(imageSlideshow);
            panel.add(spectrumEnergy);
            panel.add(circularSpectrum);
            panel.add(starlightSpectrum);

            panel.add(new JLabel(languageManager.getPanelText("production.video.title")));
            JTextField videoTitleField = new JTextField(20);
            
            boolean keepOriginalSpeed = keepOriginalSpeedCheckBox.isSelected();
            if (keepOriginalSpeed) {
                videoTitleField.setText(languageManager.getPanelText("production.video.default.title.no.bpm"));
            } else {
                int targetBpm = targetBpmSlider.getValue();
                videoTitleField.setText(languageManager.getPanelText("production.video.default.title", targetBpm));
            }
            
            panel.add(videoTitleField);

            Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(ProductionPanel.this);
            int result = JOptionPane.showConfirmDialog(parentFrame, panel, languageManager.getString("panel.production.video.resolution.style.title"), JOptionPane.OK_CANCEL_OPTION,
                    JOptionPane.QUESTION_MESSAGE);

            if (result != JOptionPane.OK_OPTION) {
                return;
            }

            if (horizontal720p.isSelected()) {
                videoParams[0] = "720p";
                videoParams[1] = "true";
            } else if (horizontal1080p.isSelected()) {
                videoParams[0] = "1080p";
                videoParams[1] = "true";
            } else if (vertical720p.isSelected()) {
                videoParams[0] = "720p";
                videoParams[1] = "false";
            } else if (vertical1080p.isSelected()) {
                videoParams[0] = "1080p";
                videoParams[1] = "false";
            }

            appDataManager.setVideoResolutionPreference(videoParams[0], Boolean.parseBoolean(videoParams[1]));

            if (spectrumEnergy.isSelected()) {
                appDataManager.setVideoStylePreference("spectrum");
            } else if (circularSpectrum.isSelected()) {
                appDataManager.setVideoStylePreference("circular");
            } else if (starlightSpectrum.isSelected()) {
                appDataManager.setVideoStylePreference("starlight");
            } else {
                appDataManager.setVideoStylePreference("slideshow");
            }
            
            videoTitle = videoTitleField.getText();
        }

        // 检查生成次数，只有在生成次数超过2次且用户未捐赠时才显示捐赠对话框
        if (!DonationDialog.hasDonated() && appDataManager.getGenerationCount() >= 2) {
            SwingUtilities.invokeLater(() -> {
                DonationDialog donationDialog = new DonationDialog(
                        (Frame) SwingUtilities.getWindowAncestor(ProductionPanel.this),
                        "generate");
                donationDialog.setVisible(true);
            });
        }

        // 增加生成次数计数器
        appDataManager.incrementGenerationCount();

        generateSingleButton.setEnabled(false);
        generateMixButton.setEnabled(false);
        generateVideoButton.setEnabled(false);
        stopButton.setEnabled(true);
        stopButton.setText(languageManager.getPanelText("production.stop"));
        progressBar.startAnimation();

        double targetBpm = targetBpmSlider.getValue();
        File outputDir;
        outputDir = new File(baseOutputDir, "out_audio");
        if (!outputDir.exists()) {
            outputDir.mkdirs();
        }
        
        File tempDir = AppDataManager.getInstance().getTempDirectory().toFile();
        List<File> filesToProcess = new ArrayList<>(selectedFiles);
        
        float drumVolume = 0.8f;
        int availableProcessors = Runtime.getRuntime().availableProcessors();
        int parallelTaskCount = DonationDialog.hasDonated()
                ? Math.max(1, availableProcessors)
                : 1;
        double plannedDuration = appStateManager.getPlannedDuration();

        String videoResolution = videoParams[0];
        boolean isLandscape = Boolean.parseBoolean(videoParams[1]);
        String videoStyle = appDataManager.getVideoStylePreference();
        boolean keepOriginalSpeed = keepOriginalSpeedCheckBox.isSelected();

        SongMetadataExtractor.AnalysisProgressCallback progressCallback = new SongMetadataExtractor.AnalysisProgressCallback() {
            @Override
            public void onProgressUpdate(String message, int progress, File currentFile) {
                if (isStoppingOperation) {
                    SwingUtilities.invokeLater(() -> {
                        progressBar.setValue(0);
                        progressBar.setIndeterminate(true);
                        progressBar.setString("");
                    });
                    return;
                }
                
                SwingUtilities.invokeLater(() -> {
                    progressBar.setValue(progress);
                    progressBar.setIndeterminate(false);
                    progressBar.setString(message);
                    if (progress > 0 && !progressBar.isAnimating()) {
                        progressBar.startAnimation();
                    }
                });
            }

            @Override
            public void onFileAnalysisComplete(File file) {
                AppStateManager appStateManager = AppStateManager.getInstance();
                appStateManager.setBpmFileAcquired(file);
            }
            
            @Override
            public void onBPMTaskComplete() {
                appStateManager.updateSelectedFiles();
                SwingUtilities.invokeLater(() -> {
                    progressBar.stopAnimation();
                });
            }
            
            @Override
            public void onOtherTaskComplete() {
                SwingUtilities.invokeLater(() -> {
                    progressBar.stopAnimation();
                });
            }
        };

        PlaybackStateManager playbackStateManager = PlaybackStateManager.getInstance();
        int beatSoundType = playbackStateManager.getBeatSoundType();
        float beatVolume = playbackStateManager.getBeatVolume();
        float backgroundVolume = playbackStateManager.getBackgroundVolume(); // 获取背景音量
        boolean truncateExceedingFiles = appStateManager.isTruncateExceedingFiles();
        LogUtil.debug("ProductionPanel", "generateTracks", languageManager.getString("production.log.truncate.status", truncateExceedingFiles));

        MusicGenerationParams params = new MusicGenerationParams(
                filesToProcess,
                keepOriginalSpeed ? -1 : targetBpm,
                outputDir,
                tempDir,
                plannedDuration,
                drumVolume,
                backgroundVolume, // 添加背景音量参数
                beatSoundType,
                videoResolution,
                isLandscape,
                videoStyle,
                generationType,
                parallelTaskCount,
                truncateExceedingFiles,
                videoTitle
        );
        LogUtil.debug("ProductionPanel", "generateTracks", languageManager.getString("production.log.params.truncate.status", params.isTruncateExceedingFiles()));
        
        currentWorker = new SwingWorker<Void, ProgressUpdate>() {
            private RunningMusicGenerator musicGenerator;
            
            @Override
            protected Void doInBackground() throws Exception {
                musicGenerator = new RunningMusicGenerator();
                musicGenerator.generateRunningTracks(params, progressCallback);
                return null;
            }
            
            @Override
            protected void done() {
                SwingUtilities.invokeLater(() -> {
                    generateSingleButton.setEnabled(true);
                    generateMixButton.setEnabled(true);
                    generateVideoButton.setEnabled(true);
                    stopButton.setEnabled(false);
                    resetProgressBar();
                    
                    String baseOutputDir = appStateManager.getAudioDirectory();
                    File outputDir = new File(baseOutputDir, "out_audio");
                    File openDir = outputDir;
                    
                    switch (generationType) {
                        case "single":
                            openDir = new File(outputDir, "run_single");
                            break;
                        case "mix":
                            openDir = new File(outputDir, "run_mix");
                            break;
                        case "mix_video":
                            openDir = new File(outputDir, "run_video");
                            break;
                        default:
                            openDir = outputDir;
                            break;
                    }
                    
                    if (openDir.exists() && openDir.isDirectory()) {
                        try {
                            Desktop.getDesktop().open(openDir);
                        } catch (Exception ex) {
                            LogUtil.error("ProductionPanel", "done", languageManager.getString("production.log.open.folder.error", ex.getMessage()));
                        }
                    } else {
                        if (outputDir.exists() && outputDir.isDirectory()) {
                            try {
                                Desktop.getDesktop().open(outputDir);
                            } catch (Exception ex) {
                                LogUtil.error("ProductionPanel", "done", languageManager.getString("production.log.open.folder.error", ex.getMessage()));
                            }
                        }
                    }
                });
            }
        };
        currentWorker.execute();
    }

    private static class ProgressUpdate {
        String message;
        double progress;

        ProgressUpdate(String message, double progress) {
            this.message = message;
            this.progress = progress;
        }
    }

    private void stopCurrentOperation() {
        isStoppingOperation = true;
        
        if (currentWorker != null && !currentWorker.isDone()) {
            try {
                SwingWorker<Void, ProgressUpdate> worker = currentWorker;
                new Thread(() -> {
                    try {
                        Field[] fields = worker.getClass().getDeclaredFields();
                        for (Field field : fields) {
                            if (field.getType().getName().equals("luke.audio.generation.RunningMusicGenerator")) {
                                field.setAccessible(true);
                                Object generator = field.get(worker);
                                Method stopMethod = generator.getClass().getMethod("stopGeneration");
                                stopMethod.invoke(generator);
                                break;
                            }
                        }
                        
                        worker.cancel(true);
                    } catch (Exception e) {
                        LogUtil.error("ProductionPanel", "stopCurrentOperation", "停止操作失败: " + e.getMessage());
                    }
                }).start();
            } catch (Exception e) {
                LogUtil.error("ProductionPanel", "stopCurrentOperation", "无法访问RunningMusicGenerator实例: " + e.getMessage());
            }
        }
    }

    private void resetUIAfterStop() {
        resetProgressBar();
        generateSingleButton.setEnabled(true);
        generateMixButton.setEnabled(true);
        generateVideoButton.setEnabled(true);
        stopButton.setEnabled(false);
        stopButton.setText(languageManager.getPanelText("production.stop"));
        isStoppingOperation = false;
    }

    private void persistTargetBpm(int bpm) {
        prefs.putInt("targetBpm", bpm);
    }

    private void persistKeepOriginalSpeed(boolean keepOriginalSpeed) {
        prefs.putBoolean("keepOriginalSpeed", keepOriginalSpeed);
    }

    private void loadPersistedSettings() {
        int persistedBpm = prefs.getInt("targetBpm", 180);
        targetBpmSlider.setValue(persistedBpm);
        targetBpmLabel.setText(String.valueOf(persistedBpm));

        boolean persistedKeepOriginalSpeed = prefs.getBoolean("keepOriginalSpeed", false);
        keepOriginalSpeedCheckBox.setSelected(persistedKeepOriginalSpeed);
        targetBpmSlider.setEnabled(!persistedKeepOriginalSpeed);
        targetBpmLabel.setEnabled(!persistedKeepOriginalSpeed);
    }
}
